import Jwt from 'jsonwebtoken';
import { jwtConfig, unlessConfig } from '../config/app.config';
import { Context } from 'koa';

export type CheckOptions = {
  pass: boolean;
  credential?: string;
  payload?: any;
  message: string;
};

export function sign(payload: PayloadOptions, options?: Jwt.SignOptions) {
  return Jwt.sign(payload, jwtConfig.secret, options || jwtConfig.signOptions);
}

export function verfiy(token: string) {
  return Jwt.verify(token, jwtConfig.secret);
}

export function unless(path: string) {
  return unlessConfig.path.some(function (p) {
    return (typeof p === 'string' && p === path) || (p instanceof RegExp && !!p.exec(path));
  });
}

/**
 * 检查请求头中是否有token
 * @param context
 */
export const checkCarry = (context: Context) => {
  const { header, cookies } = context;
  const result: CheckOptions = {
    pass: false,
    credential: '',
    message: 'auth denied',
  };
  if (header && header.authorization) {
    result.pass = true;
    result.credential = header.authorization;
    result.message = 'auth passed';
  } else if (cookies && cookies.get('authorization')) {
    result.pass = true;
    result.credential = cookies.get('authorization');
    result.message = 'auth passed';
  }
  return result;
};

/**
 * 检查token的scheme是否正确
 * @param token
 */
export const checkScheme = (token: string) => {
  const result: CheckOptions = {
    pass: false,
    credential: '',
    message: 'Bad Authorization header format. Format is "Authorization: Bearer <token>"',
  };
  const parts = token.trim().split(' ');
  if (parts.length === 2) {
    const scheme = parts[0];
    if (/^Bearer$/i.test(scheme)) {
      result.pass = true;
      result.credential = parts[1];
      result.message = 'Good Authorization header format.';
    }
  }
  return result;
};

/**
 * 检查token是否合法
 * @param token
 */
export const checkValid = (token: string) => {
  const result: CheckOptions = {
    pass: false,
    payload: '',
    message: 'malformed jwt',
  };
  try {
    const deocded = verfiy(token);
    result.pass = true;
    result.payload = deocded;
    result.message = 'jwt valid';
  } catch (error: any) {
    // result.message = error['name'] == 'TokenExpiredError' ? 'expired jwt' : 'invalid jwt';
    result.message = error['message'];
  }
  return result;
};
